package main

import (
	"gocv.io/x/gocv"
	"sync"
	"time"
)

var (
	ShipUps   sync.Map //上游区船舶
	ShipDowns sync.Map //下游区船舶
	CountUp   sync.Map //向上游行驶的数量 最大值7分钟限制
	CountDown sync.Map //向下游行驶的数量 最大值5分钟限制
	StateDown int      //下游区信号灯状态，0-关闭，1-上行允许，2-禁行
	StateUp   int      //上游区信号灯状态，0-关闭，1-下行允许，2-禁行
)

//region ROI 识别区
type ROI struct {
	X, Y, W, H int     //x, y - 左上角（象素），w, h - 宽度和高度（象素）
	classId    int     // 类别id
	confidence float64 // 置信度
	secondtime int64   // 记录每次检测的时间
}

func NewROI(x, y int, w, h int) ROI {
	roi := ROI{X: x, Y: y, W: w, H: h}
	return roi
}

func (the *ROI) IsEqual(roi ROI) bool {
	result := the.X == roi.X && the.Y == roi.Y && the.W == roi.W && the.H == roi.H
	return result
}

func (the *ROI) Area() int {
	return the.W * the.H
}

//endregion

//region Ship
type Ship struct {
	MaxDT int64    //日期时间
	Roi   ROI      //在图片中ROI区域
	Hist  gocv.Mat //灰度规范化后直方图
	Area  int      //面积，象素

	waitMins int64 // 等待时间

	State      int      //船舶状态，0-新发现，1-行驶中
	Y0         int      //上次的中心位置Y
	Count      int      //计算Y值偏移的间隔数，每3次计算1次dy，用于判断方向
	Direction  int      //行驶方向，0：未知；-1：上行，1：下行
	Speed      float64  //速度，m/s
	Load       float64  //载重量，t
	MaxArea    int      //最大面积
	MaxImg     gocv.Mat //船舶最大时的图片
	NoMatch    int      //连续未匹配次数，注：一旦匹配后该值清0
	Flag       bool     // 是否离开单通道
	cameraZone int8     //摄像头视角

	//Shift int  //位移，象素，用于计算速度时的位移
	//Height int  // 舷高，象素，用于计算载重量时的舷高
}

func NewShip(roi ROI) Ship {
	time := time.Now().Unix()
	ship := Ship{MaxDT: time, Roi: roi, waitMins: time, Hist: gocv.NewMat(), MaxImg: gocv.NewMat()}
	return ship
}

func (the *Ship) IsEqual(ship Ship) bool {
	result := the.Roi == ship.Roi
	return result
}

//endregion

//region Matcher
type Matcher struct {
	ind       int     //船舶序号
	intersect bool    //边框是否相交
	dy        int     //纵向距离
	correl    float32 //直方图相关度
	bDist     float32 //巴氏距离
}

//endregion

//region ShipCount
type ShipCount struct {
	id        int64 // 删除时使用
	startTime int64 // 船舶进入通道的时间
	waitMins  int64 // 等待时间
	photo     gocv.Mat
}

func NewShipCount(roi ROI) Ship {
	time := time.Now().Unix()
	ship := Ship{MaxDT: time, Roi: roi, waitMins: time}
	return ship
}

func (the *ShipCount) IsEqual(shipCount ShipCount) bool {
	result := the.id == shipCount.id
	return result
}

//endregion

//region SignalMode
type SignalMode struct {
	waitDownCount int
	dowingCount   int
	waitUpCount   int
	upingCount    int
	stateUp       int
	stateDown     int
	waitMins      int64 // 等待时间
	passMins      int64 // 通行时间
	Direction     int
	photo         []byte
}
